# -*- coding: utf-8 -*-

"""
http 客户端
"""
import sys, os, time, re
import gzip
import urllib.request
import ppc.extensions.log as log

#  获取网页内容
def request(url, data = None, headers = {}, urlencode = True, decode = True, timeout = 60):
    try:
        if data and type(data) != bytes:
            if urlencode:
                data = urllib.parse.urlencode(data)
            data = data.encode('utf-8')
        
        req = urllib.request.Request(url, data)
        req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31")
        for k, v in headers.items():
            req.add_header(k, v)

        f = urllib.request.urlopen(req, timeout = timeout)
        
        code = f.getcode()
        if code < 200 or code >= 300:
            log.error('error occurs when openning url "{0}". status code {1}.'.format(url, code))
            return None
    except Exception as ex:
        log.error('error occurs when openning url "{0}". exception "{1}."'.format(url, str(ex)))
        return None

    try:
        data = f.read()
    except Exception as ex:
        log.error('error occurs when reading url "{0}". exception "{1}."'.format(url, str(ex)))
        return None

    # gzip解压缩
    if f.headers['Content-Encoding'] == 'gzip':
        data = gzip.decompress(data)

    # 不解码
    if not decode:
        return data

    # 检测网页编码

    charsetlist = re.findall(r"""charset=(?P<quot>['"]?)([^'"]+)(?P=quot)""", data.decode('utf-8', errors='ignore'))
    charset = None
    if len(charsetlist) > 0:
        (quot, charset) = charsetlist[0]
        charset = charset.lower()
    if not charset or \
       not re.match(r"""^([a-z][a-z0-9\-]+)$""", charset):
        charset = 'utf-8'
    if charset == 'gb2312':
        charset = 'gbk'
    
    # 解码网页内容
    try:
        html = data.decode(charset)
    except UnicodeDecodeError as ex:
        log.error('error occurs when decoding page "{0}". exception "{1}."'.format(url, str(ex)))
        return None
    
    # 返回页面内容
    return html

# 使用multipart/form-data格式来提交表单
def multipost(url, fields, files = []):
    boundary = '----------{0}'.format(hex(int(time.time() * 1000)))
    data = []
    data.append('--%s' % (boundary))

    for k, v in fields.items():
        data.append('Content-Disposition: form-data; name="{0}"\r\n'.format(k))
        data.append(v)
        data.append('--%s' % (boundary))

    for f in files:
        data.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (f['name'], f['filename']))
        data.append('Content-Type: application/octet-stream\r\n')
        if 'data' in f:
            data.append(f['data'])
        else:
            with open(f['filename'], 'rb') as r:
                data.append(r.read())
        data.append('--%s--\r\n' % (boundary))

    b = []
    for v in data:
        if isinstance(v, str):
            b.append(v.encode('utf-8'))
        else:
            b.append(v)

    http_body = b'\r\n'.join(b)
    
    html = request(url, http_body, 
        {'Content-Type': 'multipart/form-data; boundary=%s' % (boundary)},
        urlencode = False)

    return html

